<?php

namespace App\Models\Traits;

use Carbon\Carbon;
use App\Models\User;
use App\Models\GoldSplit;
use App\Models\GoldRecord;
use Rainsens\Dinglog\Facades\Dinglog;

trait GoldRecordTrait
{
	public static function sRobotRecordsCount($rid): int
	{
		$mockedUserIds = User::where('is_mock', true)->pluck('id');
		return self::where('gold_round_id', $rid)
			->whereIn('user_id', $mockedUserIds)
			->whereDate('created_at', Carbon::today())
			->whereNotNull('paid_at')
			->count();
	}

	public function cacheKey(): string
	{
		$userId = $this->user_id;
		$date = $this->created_at->format('Ymd');
		$rid = $this->gold_round_id;
		$pid = $this->gold_product_id;

		return "{$userId}_{$date}_{$rid}_{$pid}";
	}

	public function isPaid(): bool
	{
		return (bool)$this->paid_at;
	}

	public function isClosed(): bool
	{
		return (bool)$this->closed_at;
	}

	public function isSettled(): bool
	{
		return (bool)$this->settled_at;
	}

	public function isRewarded(): bool
	{
		return (bool)$this->rewarded_at;
	}

	public function isFinished(): bool
	{
		return (bool)$this->finished_at;
	}

	public function hasAppliedToResell(): bool
	{
		return (bool)$this->to_resell_applied_at;
	}

	public function hasAppliedToSplit(): bool
	{
		return (bool)$this->to_split_applied_at;
	}

	public function hasAppliedToTake(): bool
	{
		return (bool)$this->to_take_applied_at;
	}

    public function settle(GoldRecord $upRecord)
    {
        $price = $upRecord->pay_net_price;
        $beans = $upRecord->pay_gold_beans;
        $profit = $upRecord->profit_after_resold;
        $data = ['up_gold_record_id' => $upRecord->id, 'gold_record_id' => $this->id];
        account_coins($upRecord->user)->plusResellingCoins($price, $data);
        account_coins($upRecord->user)->plusResellingBeansCoins($beans, $data);
        account_coins($upRecord->user)->plusResellingProfitCoins($profit, $data);
    }

    public function isSplit(): bool
    {
        return $this->goldSplits()->exists();
    }

    public function isSplitSettled(): bool
    {
        return $this->splitsSettledCount() >= $this->splitsAllCount();
    }

    public function splitsAllCount(): int
    {
        return max((int)$this->goldSeed->split_amount, 0);
    }

    public function splitsAllMoney()
    {
       $splitPrice = big_decimal($this->goldSeed->split_price);
        if ($splitPrice->isLessThanOrEqualTo(0)) {
            return big_decimal(0);
        } else {
            return $splitPrice;
        }
    }

    public function splitsSettledCount(): int
    {
        return $this->goldSplits()->whereNotNull('settled_at')->count();
    }

    public function splitsSettledMoney()
    {
        return $this->goldSplits()->whereNotNull('settled_at')->sum('split_price');
    }

    public function needSettledSplit()
    {
        return GoldSplit::query()
            ->where('new_gold_product_id', $this->gold_product_id)
            ->whereNull('settled_at')
            ->first();
    }

    public function nextResellAt(): string
    {
        $nextDay = $this->created_at->addDay();

        if ($this->goldRound->is_ending) {
            $nextDay = null;
        } elseif ($this->isFinished()) {
            $nextDay = null;
        } elseif ($this->hasAppliedToResell()) {
            $nextDay = $this->to_resell_applied_at->addDay();
        } elseif ($this->hasAppliedToSplit() and !$this->isSplitSettled()) {
            $nextDay = $this->goldSplits()->first()->started_at;
        }

        if (! $nextDay) return '';
        /*$offWeekdays = cs('storm')->rest_weekdays;

        if (count($offWeekdays) <= 0) return $nextDay->toDateString();

        foreach ($offWeekdays as $offDay) {
            if ($offDay == 'Mon' and $nextDay->isMonday()) {
                $nextDay->addDay();
            } elseif ($offDay == 'Tue' and $nextDay->isTuesday()) {
                $nextDay->addDay();
            } elseif ($offDay == 'Wed' and $nextDay->isWednesday()) {
                $nextDay->addDay();
            } elseif ($offDay == 'Thu' and $nextDay->isThursday()) {
                $nextDay->addDay();
            } elseif ($offDay == 'Fri' and $nextDay->isFriday()) {
                $nextDay->addDay();
            } elseif ($offDay == 'Sat' and $nextDay->isSaturday()) {
                $nextDay->addDay();
            } elseif ($offDay == 'Sun' and $nextDay->isSunday()) {
                $nextDay->addDay();
            }
        }*/

        $openedAt = $this->goldRound->today_opened_at;
        return $nextDay->hour($openedAt->hour)->minute($openedAt->minute)->second(0)->toDateTimeString();

    }


     public function nextResellAtProduct(): string
    {
        $nextDay = $this->created_at->addDay();

        if ($this->goldRound->is_ending) {
            $nextDay = null;
        } elseif ($this->isFinished()) {
            $nextDay = null;
        } elseif ($this->hasAppliedToResell()) {
            $nextDay = $this->created_at->addDay();
        } elseif ($this->hasAppliedToSplit() and !$this->isSplitSettled()) {
            $nextDay = $this->goldSplits()->first()->started_at;
        }

        if (! $nextDay) return '';
        $offWeekdays = cs('storm')->rest_weekdays;

        if (count($offWeekdays) <= 0) return $nextDay->toDateString();

        foreach ($offWeekdays as $offDay) {
            if ($offDay == 'Mon' and $nextDay->isMonday()) {
                $nextDay->addDay();
            } elseif ($offDay == 'Tue' and $nextDay->isTuesday()) {
                $nextDay->addDay();
            } elseif ($offDay == 'Wed' and $nextDay->isWednesday()) {
                $nextDay->addDay();
            } elseif ($offDay == 'Thu' and $nextDay->isThursday()) {
                $nextDay->addDay();
            } elseif ($offDay == 'Fri' and $nextDay->isFriday()) {
                $nextDay->addDay();
            } elseif ($offDay == 'Sat' and $nextDay->isSaturday()) {
                $nextDay->addDay();
            } elseif ($offDay == 'Sun' and $nextDay->isSunday()) {
                $nextDay->addDay();
            }
        }

        $openedAt = $this->goldRound->today_opened_at;
        return $nextDay->hour($openedAt->hour)->minute($openedAt->minute)->toDateTimeString();

    }
}
